package com.miyake.server.servlet;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.jdo.PersistenceManager;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItemIterator;
import org.apache.commons.fileupload.FileItemStream;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.miyake.server.DsData;
import com.miyake.server.DsImage;
import com.miyake.server.DsUser;
import com.miyake.server.PMF;
import com.miyake.server.user.UserManager;

public class FileServlet extends HttpServlet implements Servlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = 7363209644430216295L;

	private static final Map<String, byte[]> chartMap = new HashMap<String, byte[]>();
	private static final FileCache fileCache = new FileCache("http://doctorssns.appspot.com/fileServlet");
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
				
		String type = "";
		if (req.getParameter("type") != null) {
			type = req.getParameter("type").toString();
		}
		String key = "";
		if (req.getParameter("key") != null) {
			key = req.getParameter("key").toString();	
		}
		
		if (type.equals("") && key.equals("")) {
			testResponse(req, resp);
		}
		
		if (type.equals("filelist")) {
			fileCache.createListPage(req, resp);
			return;
		}
//		DsImage image = NodeManager.getInstance().getImage(key);
		PersistenceManager pm = PMF.get().getPersistenceManager();
		try {
			if (type.equals("image")) {
				DsImage image = pm.getObjectById(DsImage.class, key);
				resp.setContentType("image/jpeg"); 
				byte[] b = image.getBin();
				resp.getOutputStream().write(b ,0, b.length);
				resp.getOutputStream().flush();
				resp.getOutputStream().close();

			}
			else if(type.equals("original")){
				DsData data = pm.getObjectById(DsData.class, key);//
//				resp.setContentType("image/jpeg"); 
				byte[] b = data.getOriginalData();
				resp.getOutputStream().write(b ,0, b.length);
				
				resp.setContentType("application/octet-stream");
				String filename = data.getFileName();
				resp.setHeader("Content-disposition", "attachment; filename=" + filename);
				resp.getOutputStream().flush();
				resp.getOutputStream().close();
			}
			else if (type.equals("chart")) {
				byte[] b = chartMap.get(key);
				chartMap.remove(key);
				resp.getOutputStream().write(b, 0, b.length);
				resp.getOutputStream().flush();
				resp.getOutputStream().close();
			}
			else if (type.equals("csv")) {
				DsData data = pm.getObjectById(DsData.class, key);//
				String[][] arr = new String[data.getColumnCount()][];
				for (int i = 0; i < data.getColumnCount(); i++) {
					arr[i] = data.getDataString(i);
				}
				
				for (String t : data.getTitles()) {
					resp.getWriter().print(t + ",");
				}
				resp.getWriter().println();
				for (int i = 0; i < data.getCount(); i++) {
					String s = "";
					for (int j = 0; j < data.getColumnCount(); j++) {
						s += arr[j][i].trim() + ",";
					}
					resp.getWriter().println(s);
				}
				resp.setContentType("text/csv"); 
				resp.getWriter().flush();
				resp.getWriter().close();
			}
			else {
				testResponse(req, resp);				
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		finally {
			pm.close();
		}

	}

	protected void testResponse(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		resp.setContentType("text/plain"); 
		resp.getWriter().println("File Servlet");
		UserService userService = UserServiceFactory.getUserService();
	    String thisURL = req.getRequestURI();        
	    resp.setContentType("text/html");             
	    PrintWriter pw = resp.getWriter();     
	    
	    if (req.getUserPrincipal() == null) {            
	    	pw.println("<a href=\"" + userService.createLoginURL(thisURL) + "\">Login</a>");        
	    	}        
	    else {            
	    	User user = userService.getCurrentUser();            
	    	pw.println("<a href=\"" + userService.createLogoutURL(thisURL) + "\">Logout</a><br/>");            
	    	pw.println("name = " + req.getUserPrincipal().getName() + "<br/>");            
	    	pw.println("isAdmin = " + userService.isUserAdmin() + "<br/>");            
	    	pw.println("domain = " + user.getAuthDomain() + "<br/>");            
	    	pw.println("email = " + user.getEmail() + "<br/>");            
	    	pw.println("nickname = " + user.getNickname() + "<br/>");  
	    	for (Map.Entry<String, byte[]> b : chartMap.entrySet()) {
	    		pw.println("<a href=\"" + b.getKey() +  "\">" + b.getKey() +  "</a>");
	    	}
//	    	for (DsUser u : UserManager.getInstance().getUserList()) {
	    		//pw.println(u.getName());
//	    	}
//	    	String userKey = UserManager.getInstance().getUserByEmail(user.getEmail()).getEncodedKey();
//	    	pw.println("userKey = " + userKey);
	    	//	    	for (DsNode node : NodeManager.getInstance().getRootNodes(userKey)) {
//	    		pw.println(node.getName());
//	    	}
    	}

//		resp.getWriter().println(userService.createLoginURL("http://localhost:8888/fileServlet"));	
		
		resp.getWriter().flush();
		resp.getWriter().close();
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		if (req.getParameter("test") != null) {
			testPost(resp);
			resp.getWriter().flush();
			resp.getWriter().close();
			return;
		}
		String name = "";
		if (req.getParameter("name") != null) {
			name = req.getParameter("name");
		}
		String key = "";
		if (req.getParameter("key") != null) {
			key = req.getParameter("key");
		}
		
		if (name == "" && key == "") {
//			testResponse(req, resp);		
		}
		
		if (req.getParameter("upload") != null && req.getParameter("upload").equals("external")) {
			fileCache.cacheFile(req, resp);
			return;
		}
		
		try {
			ServletFileUpload upload = new ServletFileUpload();  
	    	int sizeMax = -1;
	    	upload.setSizeMax(sizeMax);
	    	upload.setFileSizeMax(sizeMax);
	    	resp.setContentType("text/plain");        
	    	FileItemIterator iterator = upload.getItemIterator(req);       

	    	while (iterator.hasNext()) {           
	    		FileItemStream item = iterator.next(); 
	    		
	    		InputStream stream = item.openStream();
	    		BufferedInputStream bis = new BufferedInputStream(stream);  
///	    			log.warning("Got an uploaded file: " + item.getFieldName() +                       
//	    					", name = " + item.getName());   
 //   			BufferedInputStream bis = new BufferedInputStream(bufstream);
    			String ret = "";
    			if (item.getContentType().contains("image")) {
    				new StoreImage(bis, key, name);
    			}   
    			else {
    				if (isXML(name)) {
    					new StoreXML(bis, key, name);
    				}
    				else if (isCSV(name)) {
    					new StoreCSV(bis, key, name);
    				}
    				else {
    					new StoreCustom(bis, key, name);
    				}
    			}
	        	resp.getWriter().print(ret);
	        	resp.flushBuffer();
	    	}
	    } catch (Exception ex) {       
	    	resp.getWriter().print(ex.toString());
	    	resp.flushBuffer();
	    	throw new ServletException(ex);     
	    }
	}

	private void testPost(HttpServletResponse resp) {
		for (DsUser user : UserManager.getInstance().getUserList()) {
			try {
				resp.getWriter().print(user.getName());
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	private boolean isCSV(String name) {
		return name.substring(name.length() - 3,name.length()).equalsIgnoreCase("csv");
	}

	private boolean isXML(String name) {
		return name.substring(name.length() - 3,name.length()).equalsIgnoreCase("xml");
	}

	public synchronized static Map<String, byte[]> getChartMap() {
		return chartMap;
	}
	
	public static Map<String, byte[]> getCacheFile() {
		return fileCache.getFileList();
	}
}
